#include "linkstack.h"
#include <stdio.h>
#include "linklist.h"
#include <stdlib.h>
#include <string.h>

typedef struct Teacher //链表业务节点
{
        LinkListNode node; //第一个域
        void* item; //栈的业务节点
}Teacher;

typedef struct TagLinkStackNode //链表业务节点
{
        LinkListNode node; //第一个域
        void* item; //栈的业务节点
}TLinkStackNode;

//创建一个栈 相当于 创建一个线性表
LinkStack* LinkStack_Create(){  
        return LinkList_Create();
}

//销毁一个栈 相当于 销毁一个线性表
void LinkStack_Destory(LinkStack* stack){
        LinkStack_Clear(stack);
        LinkList_Destory(stack);
}

//清空一个栈 相当于 清空一个线性表
//清空栈的时候 涉及到 栈元素声明周期的管理
        //所有入栈的节点 都是malloc出来的；
        //若要清空栈,把栈中元素弹出，并且释放节点内存
void LinkStack_Clear(LinkStack* stack){
        if(stack == NULL){
                return;
        }
        while ( LinkStack_Size(stack) > 0 ){
                LinkStack_Pop(stack); //在这个函数释放节点的内存
        }
}

//向栈中添加元素 相当于 向线性表头部插入元素
//void* item 栈的业务节点 --- > 转换成链表的业务节点
int LinkStack_Push(LinkStack* stack, void* item){
        TLinkStackNode* tmp = NULL;
        int ret = 0;

        tmp = (TLinkStackNode *)malloc(sizeof(Teacher));
        if(tmp == NULL){
                return -1;
        }
        memset(tmp, 0, sizeof(TLinkStackNode));
        tmp->item = item;

        //int LinkList_Insert(LinkList* list, LinkListNode* node, int pos)
        ret = LinkList_Insert(stack, (LinkListNode *)tmp, 0);
        if(ret != 0){
                printf("func LinkList_Insert() error:%d\n", ret);
                if(tmp != NULL){
                        free(tmp);
                        tmp = NULL;
                }
                return ret;
        }

        return ret;
}

//从栈中弹出元素 相当于 从线性表的头部删除元素
//把线性表的业务节点 转换成 栈的业务节点
void* LinkStack_Pop(LinkStack* stack){
        void* item = NULL; //栈的业务节点
        TLinkStackNode* tmp = NULL;
        
        tmp = (TLinkStackNode *)LinkList_Delete(stack, 0);
        if(tmp ==NULL){
                return NULL;
        }
        
        item = tmp->item;

        //因为LinkStack_Push的时候LinkList_Insert 分配了内存,所以LinkStack_Pop中的  LinkList_Delete 之后 要释放内存
        free(tmp);

        return item;
}

//获取栈顶元素 相当于 获取线性表的0号(头部)位置
void* LinkStack_Top(LinkStack* stack){
        TLinkStackNode* tmp = NULL;

        tmp = (TLinkStackNode*)LinkList_Get(stack, 0);
        if(tmp == NULL){
                return NULL;
        }

        return tmp->item;
}

//求栈的大小 相当于求线性表的大小
int LinkStack_Size(LinkStack* stack){
        return LinkList_Length(stack);
}